package com.flying.str;

import org.junit.Test;

import javax.lang.model.SourceVersion;
import java.io.UnsupportedEncodingException;
import java.time.format.TextStyle;
import java.util.Arrays;

/**
 * @author 刘鹏飞
 * @ClassName StringDemo
 * @Date 2024/12/21 13:21
 * @Created by 刘鹏飞
 * @Description 测试字符串的使用
 */
public class StringDemo {

    /*
    结论
    1. 常量与常量的拼接结果在常量池中,且常量池中不会存在相同内容的常量
    2. 只要其中有一个是变量,结果就在堆空间中
    3. 如果拼接的结果调用intern()方法,返回值就在常量池中
     */
    
    @Test
    public void test1(){
        String s1="javaEEHadoop";
        String s2="javaEE";  //常量池中

        String s3 = s2 + "Hadoop";   //  堆空间中的对象
        System.out.println(s3==s1);    // false

        final String s4="javaEE";  // 被final修饰的是常量,也在常量池中

        String s5=s4+"Hadoop";
        System.out.println(s1==s5);   //  true

    }
    

    @Test
    public void test2(){

        String s1 = "javaEE";
        String s2 = "hadoop";

        //  1. 字面量参与的是在常量池中,
        //  2. 只要有变量参与的是在堆空间中通过new的方式创建字符串的

        String s3 = "javaEEhadoop";
        String s4 = "javaEE" + "hadoop";
        String s5 = s1 + "hadoop";
        String s6 = "javaEE" + s2;
        String s7 = s1 + s2;


        System.out.println(s3 == s4);  //  true
        System.out.println(s3 == s5);  //  false
        System.out.println(s3 == s6);  //  false
        System.out.println(s5 == s6);  //  false
        System.out.println(s5 == s7);  //  false
        System.out.println(s6 == s7);  //  false

        String s8 = s5.intern();   //  返回得到的s8使用的是常量池中已经存在的 "javEEhadoop"
        System.out.println(s8 == s3);   // true


    }

    /*
     String的实例化方式:
     方式一: 通过字面量定义的方式
     方式二:通过 new+构造器的方式

     面试题: String s=new String("abc);方式创建对象,在内存中创建了几个对象
            两个:一个时堆空间中的new结构,另一个时char[]对应的常量池中的数据: "abc"
    */

    @Test
    public void Test2() {

        // 通过字面量定义的方式:  此时的s1和s2的数据javaEE声明在方法区的字符串常量池中
        String s1 = "javaEE";
        String s2 = "javaEE";

        // 通过 new+构造器的方式: 此时的s3和s4保存的地址值,是数据在堆空间中开辟空间以后对应的地址值
        String s3 = new String("javaEE");
        String s4 = new String("javaEE");

        System.out.println(s1 == s2);   //  true ,两个对象地址相同
        System.out.println(s1 == s3);   //  false
        System.out.println(s1 == s4);   //  false
        System.out.println(s2 == s4);   //  false


        Person t1 = new Person("Tom", 11);
        Person t2 = new Person("Tom", 11);
        System.out.println(t1.name.equals(t2.name));
        System.out.println(t1.name == t2.name);
        System.out.println("**********************");

    }


    /*
     String: 字符串,使用一对""引起来表示
     1. String声明为final的,不能被继承
     2. String实现了Serializable接口:支持序列化,表示字符串是可序列化的
              实现了Comparable接口: 表示String可以比较大小
     3. String内部定义了 final char[] value用于存储字符串数据(JDK8);JDK9以后改为 final byte[] value.
     4. String:代表不可变的字符序列.简称:不可变性
            体现: 1. 对字符串重新赋值时,需要重写指定内存区域赋值,不能使用原有的value进行赋值
                  2. 对现有的字符串进行连接操作时,也需要重新指定内存区域赋值,不能使用原有的value进行赋值
                  3.当调用String的replace()方法修改指定字符或字符串时,也需要重新指定内存区域重新赋值
     5. 通过字面量的方式(区别于new)给一个字符串赋值,此时的字符串值声明在字符串常量池
     6. 字符串常量池中是不会存储相同内容的字符串的.

    */


    @Test
    public void test4() {
        String s1 = "abc";  // 字面量
        String s2 = "abc";
//        s1="hello";

        System.out.println(s1 == s2);  //  比较s1和s2的地址值
        System.out.println(s1);
        System.out.println(s2);

        System.out.println("****************************");

        String s3 = "abc";
        s3 += "def";
        System.out.println(s3 == s2);   //  比较s1和s3的地址值

        System.out.println("****************************");


        String s4 = "abc";

        String s5 = s4.replace('a', 'm');

        System.out.println(s4);
        System.out.println(s5);


    }


    /*
    字符串与其他结构之间的转换
     */


    /**
     * String 与 byte[] 之间的转换
     * 编码: String  -->  byte[];  调用StringDe getBytes()
     * 解码: byte[]  --> String

     *     编码: 字符串 -->  字节 (看的懂的二进制数据)
     *     解码: 字节   -->  字符串(编码的逆过程,看不懂的二进制数据 --->  看的懂)
     *
     */
    @Test
    public void test5() throws UnsupportedEncodingException {
        // 编码
        String s1="abc123中国";
        byte[] bytes = s1.getBytes();  // 默认编码集 uff8,一个中文占2个字节
        System.out.println(Arrays.toString(bytes));  // [97, 98, 99, 49, 50, 51, -28, -72, -83, -27, -101, -67]

        // 指定字符集编码

        byte[] bytes1 = s1.getBytes("gbk"); // gbk中一个中文占2个字节
        System.out.println(Arrays.toString(bytes1));  // [97, 98, 99, 49, 50, 51, -42, -48, -71, -6]

        String s = new String(bytes1);
        String s12 = new String(bytes1,"gbk");
        System.out.println("s = " + s);  // s = abc123�й�  乱码--> 编码与解码不一致

    }

    /*
     String yu  char[] 之间的转换

     String  -->  char[]: 调用String的toCharArray()


     char[]  -->  String的构造器

     */

    @Test
    public void test6(){
        String s1="abc123";

        // String --> char[]
        char[] charArray = s1.toCharArray();
        System.out.println(Arrays.toString(charArray));


        String s2 = new String(charArray);

    }

    /*
    String与基本数据类型,包装类转换
    string -> 基本数据类型,包装类 :调用包装类的静态方法 parseInt(str)/parseDouble(str)
    基本数据类型,包装类 --> String 调用 String的valueOf()
     */

    @Test
    public void test7(){
        String s1="123";
        String s2="true";
        int i = Integer.parseInt(s1);
        double v = Double.parseDouble(s1);

        boolean b = Boolean.parseBoolean(s2);



        String s4 = String.valueOf(i);
        String s3 = i + "";   //  堆空间
        System.out.println(s2);
        System.out.println(s4);

        System.out.println(s1 == s3);
    }



}   
